/**
 * 
 */
package controller.xml;

import model.session.ExecutionStatus;
import model.session.SessionBlock;
import model.session.SolverExecutionBlock;
import model.solver.SolverFactory;
import model.solver.SolverResult;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;

import controller.solver.Solver;

/**
 * Use to parse a {@link SolverExecutionBlock} in the exported session in XML.
 * 
 * @author GRONOWSKI Stephane svan001@aol.com
 * 
 *         igsat 2010
 * 
 */
public class SolverExecutionXMLHandler extends XMLHandler {

	private SolverExecutionBlock		solverBlock		= null;
	private SolverExecutionXMLStatus	status			= SolverExecutionXMLStatus.NONE;
	private ExecutionStatus				execStatus		= null;
	private Long						previousTime	= null;

	private Solver						solver			= null;
	private SolverResult				result			= null;
	private SolverFactory				factory;
	private SessionBlock				first			= null;

	public SolverExecutionXMLHandler(SessionBlock first, SolverFactory factory) {
		this.factory = factory;
		this.first = first;
	}

	@Override
	public boolean characters2(char[] ch, int start, int length) throws SAXException {
		throw new SAXException("unnexpecte behavior");
	}

	@Override
	public boolean endDocument2() throws SAXException {
		return false;
	}

	@Override
	public boolean endElement2(String uri, String localName, String qName) throws SAXException {
		switch (status) {
		case NONE:
			return false;

		case EXEC:
			if (qName.equals(XMLBaliseFormat.EXECUTION))
			{// ferme execution
				status = SolverExecutionXMLStatus.NONE;
				execStatus = ((ExecutableXMLHandler) delegate).getExecstatus();
				previousTime = ((ExecutableXMLHandler) delegate).getPreviousTime();
				if (execStatus == null || previousTime == null)
					throw new SAXException("problem EXECUTION STATUS or PREVIOUS TIME");

				delegate = null;
				return true;
			}
			throw new SAXException("end of EXECUTION was expected");

		case SOLVER:
			if (qName.equals(XMLBaliseFormat.SOLVER))
			{// ferme solver
				status = SolverExecutionXMLStatus.NONE;
				solver = ((SolverXMLHandler) delegate).getSolver();
				if (solver == null)
					throw new SAXException("problem with SOLVER");

				delegate = null;
				return true;
			}
			throw new SAXException("end of SOLVER was expected");

		case SOLVER_RESULT:
			if (qName.equals(XMLBaliseFormat.SOLVER_RESULT))
			{// ferme solver result
				status = SolverExecutionXMLStatus.NONE;
				result = ((SolverResultXMLHandler) delegate).getResult();
				if (result == null)
					throw new SAXException("problem with SOLVER RESULT");

				delegate = null;
				return true;
			}
			throw new SAXException("end of SOLVER RESULT was expected");
		}


		// attend une fin de balise qui existe pas...
		throw new SAXException("an other end of element was expected");
	}

	@Override
	public boolean startElement2(String arg0, String arg1, String arg2, Attributes arg3) throws SAXException {
		if (status != SolverExecutionXMLStatus.NONE)
			throw new SAXException("already have a started element");

		if (arg2.equals(XMLBaliseFormat.SOLVER))
		{// balise solver
			if (solver != null)
				throw new SAXException("already have a SOLVER");

			// set les donnees pour recupere le solver
			status = SolverExecutionXMLStatus.SOLVER;
			delegate = new SolverXMLHandler(factory);

			return true;
		}

		if (arg2.equals(XMLBaliseFormat.SOLVER_RESULT))
		{// balise result
			// set les donnees pour recupere le result
			status = SolverExecutionXMLStatus.SOLVER_RESULT;
			delegate = new SolverResultXMLHandler();
			return true;
		}

		if (arg2.equals(XMLBaliseFormat.EXECUTION))
		{// balise execution

			// set les donnees pour recupere le exec
			status = SolverExecutionXMLStatus.EXEC;
			delegate = new ExecutableXMLHandler();
			return true;
		}
		// peut pas commencer balise qui existe pas
		throw new SAXException("unexpected balise: " + arg2);
	}

	/**
	 * Return the solverBlock if possible, null otherwise.
	 * 
	 * @return the solverBlock
	 */
	public SolverExecutionBlock getSolverBlock() {
		if (solverBlock == null && result != null && solver != null && execStatus != null)
		{// cree le block
			solverBlock = new SolverExecutionBlock(first, execStatus, solver, result);
			solverBlock.setPreviousExecutionTime(previousTime);
		}

		return solverBlock;
	}

	/**
	 * Return the execStatus.
	 * 
	 * @return the execStatus
	 */
	public ExecutionStatus getExecStatus() {
		return execStatus;
	}

	/**
	 * Return the solver.
	 * 
	 * @return the solver
	 */
	public Solver getSolver() {
		return solver;
	}

	/**
	 * Return the result.
	 * 
	 * @return the result
	 */
	public SolverResult getResult() {
		return result;
	}


}
